package com.smh.demo1.a29;

import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistrarBeanPostProcessor;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.view.BeanNameViewResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * @author shiminghui
 * @date 2025/5/3 17:32
 * @description: TODO
 */
@Configuration
@ComponentScan
public class WebConfig {

    @Bean
    // 创建一个tomcat容器
    public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
        TomcatServletWebServerFactory servletWebServerFactory = new TomcatServletWebServerFactory();
        return servletWebServerFactory;
    }

    @Bean
    // 创建dispatcherServlet前端处理器
    public DispatcherServlet dispatcherServlet() {
        DispatcherServlet dispatcherServlet = new DispatcherServlet();
        return dispatcherServlet;
    }

    @Bean
    // 创建mapping处理器 职责: 匹配请求路径, 找到对应的控制器方法
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping();
        return requestMappingHandlerMapping;
    }

    @Bean
    // 创建adapter处理器 职责: 调用控制器方法, 完成参数解析,数据绑定,返回值处理等操作
    public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
        RequestMappingHandlerAdapter requestMappingHandlerAdapter = new RequestMappingHandlerAdapter();
        requestMappingHandlerAdapter.setMessageConverters(List.of(new MappingJackson2HttpMessageConverter()));
        return requestMappingHandlerAdapter;
    }

    @Bean
    // 注册dispatcherServlet
    public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet) {
        DispatcherServletRegistrationBean registrationBean = new DispatcherServletRegistrationBean(dispatcherServlet, "/"); // 映射路径
        registrationBean.setLoadOnStartup(0); // 启动顺序,越小优先级越高(设置这个属性后())
        return registrationBean;
    }

    @Bean
    // 注册异常页面
    public ErrorPageRegistrar errorPageRegistrar() {
        return new ErrorPageRegistrar() {
            @Override
            // 这里的操作可以实现,Tomcat捕捉到异常后,跳转到/error这个路径
            public void registerErrorPages(ErrorPageRegistry registry) {
                registry.addErrorPages(new ErrorPage("/error"));
            }
        };
    }

    @Bean
    // 错误页面注册的处理器,可以改变Tomcat默认的错误页面
    public ErrorPageRegistrarBeanPostProcessor errorPageRegistrarBeanPostProcessor() {
        return new ErrorPageRegistrarBeanPostProcessor();
    }

    @Bean
    // 错误页面控制器,就是帮我们生成一个错误页面的控制器,他的映射路径是/error
    public BasicErrorController basicErrorController() {
        ErrorProperties errorProperties = new ErrorProperties();
        errorProperties.setIncludeException(true); // 设置包含异常信息
        return new BasicErrorController(new DefaultErrorAttributes(), errorProperties);
    }

    @Bean
    // 设置返回的错误页面
    public View error() {
        return new View() {
            @Override
            public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
                System.out.println(model);
                response.setContentType("text/html;charset=utf-8");
                response.getWriter().print("""
                        <h1>服务器内部错误</h1>
                        """);
            }
        };
    }

    @Bean
    // 设置视图解析器(通过bean的名字查找)
    public ViewResolver viewResolver() {
        return new BeanNameViewResolver();
    }
}
